﻿#if NETSTANDARD
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Builder;
#endif
using CRL.Transaction.DbStatus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CRL.Transaction
{
    public class TransLoader
    {
        bool fromNetCoreInjection;
        //ITransInfoManage transInfoManage;
        public TransLoader()
        {
            //if (TransConfig._manageFunc != null)
            //{
            //    transInfoManage = TransConfig._manageFunc.Invoke();
            //}
        }
#if NETSTANDARD
        IServiceProvider provider;
        IHost host;
        public TransLoader(IServiceProvider _provider, IHost _host)
        {
            provider = _provider;
            fromNetCoreInjection = true;
            //transInfoManage = _transInfoManage;
            host = _host;
        }
#endif
        public void StartCheckThread(string projectName)
        {
            //按项目名检查
            TransConfig.projectName = projectName;
#if NETSTANDARD
            if (fromNetCoreInjection)
            {
                provider = host.Services;
                //transInfoManage = provider.GetService<ITransInfoManage>();
            }
#endif
            new Core.ThreadWork().Start("TransWorkLoad", () =>
            {
                var transInfoManage = TransConfig.GetTransInfoManage();
                transInfoManage.CreateTable();
                var all = LoadAll(projectName);
                 all.ForEach(b =>
                 {
#if NETSTANDARD
                    if (fromNetCoreInjection)
                     {
                         b.SetServiceProvider(provider);
                     }
#endif
                    b.Execute();
                 });

                 transInfoManage.DeleteCompleted();
                 return true;
             }, 180);
        }
        public List<ITransControl> LoadAll(string loadProjectName, string checkKey = "")
        {
            var transInfoManage = TransConfig.GetTransInfoManage();
            var infos = transInfoManage.QueryChecks(loadProjectName);
            if (!string.IsNullOrEmpty(checkKey))
            {
                infos = infos.FindAll(b => b.CheckKey == checkKey);
            }
            var tIds = infos.Select(b => b.TId);
            var allSteps = transInfoManage.QuerySteps(tIds);
            return infos.Select(b => Load(b, allSteps.FindAll(x => x.TId == b.TId))).ToList();
        }
        public ITransControl Load(TransMasterInfo info, List<TransStepInfo> steps)
        {
            steps = steps.OrderBy(b => b.Step).ToList();
            ITransControl control;
#if NETSTANDARD
            if (provider != null && fromNetCoreInjection)
            {
                if (info.TransactionType == TransactionType.Saga)
                {
                    control = provider.GetService<SagaControl>();
                }
                else
                {
                    control = provider.GetService<TccControl>();
                }
            }
            else
            {
                if (info.TransactionType == TransactionType.Saga)
                {
                    control = new SagaControl();
                }
                else
                {
                    control = new TccControl();
                }
            }
#else
            if (info.TransactionType == TransactionType.Saga)
            {
                control = new SagaControl();
            }
            else
            {
                control = new TccControl();
            }
#endif
            control.FromLoad = true;
            control.Status = info.Status;
            var option = new TransOptions
            {
                MaxRetryCount = info.MaxRetryCount,
                RetryInterval = TimeSpan.FromSeconds(info.RetryInterval),
                Persistent = false,
                Name = info.Name,
                TId = info.TId,
                UseLog = true
            };
            if (!string.IsNullOrEmpty(info.ArgsType))
            {
                var type = Type.GetType(info.ArgsType);
                option.Args = Core.SerializeHelper.DeserializeFromJson(info.Args, type);
            }
            control.Start(option);
            foreach (var step in steps)
            {
                var type = Type.GetType(step.TypeName);
                var argsType = Type.GetType(step.ArgsType);
                if (type == null)
                {
                    throw new Exception($"未能找到反射类型{info.Name} {step.TypeName}");
                }
                if (argsType == null)
                {
                    throw new Exception($"未能找到反射类型{info.Name} {step.ArgsType}");
                }
                control.Then(type, Core.SerializeHelper.DeserializeFromJson(step.Args, argsType), step.Status);
            }
            return control;
        }
    }
}
